﻿using Demo.Public;
using Demo.Public.Base;
using Demo.Public.Modbsus;
using StoreSystem.Models;
using System.Collections.ObjectModel;
using System.Timers;
using System.Windows;

namespace StoreSystem.ViewModels
{
    public class MainViewModel : ViewModelBase
    {
        private ObservableCollection<AlarmLogInfo> _AlarmLogList = new ObservableCollection<AlarmLogInfo>();
        private string _CurrentDateTime = string.Empty;
        private ObservableCollection<THDataInfo> _curTHDataList = new ObservableCollection<THDataInfo>();
        private DelegateCommand _ExitCommand;
        private System.Timers.Timer _readTime;
        private DelegateCommand _SelectStoreCommand;
        private StoreInfo _SelStore = null;
        private DelegateCommand _StartCommand;
        private ObservableCollection<StatisticsItem> _StatisticsItems = null;
        private DelegateCommand _StopCommand;
        private ObservableCollection<StoreInfo> _StoreInfos = null;
        private System.Timers.Timer _timeTimer;

        public MainViewModel()
        {
            CurrentDateTime = DateTime.Now.ToString("HH:mm:ss");

            InitDatasAsync().ContinueWith(task =>
            {
                SelStore = StoreInfos?.FirstOrDefault();
                LoadStoreRoomDatas();
            });
        }

        /// <summary>
        ///
        /// </summary>
        public ObservableCollection<AlarmLogInfo> AlarmLogList
        {
            get
            {
                return _AlarmLogList;
            }
            set
            {
                _AlarmLogList = value;
                RaisePropertyChanged("AlarmLogList");
            }
        }

        /// <summary>
        ///
        /// </summary>
        public string CurrentDateTime
        {
            get
            {
                return _CurrentDateTime;
            }
            set
            {
                _CurrentDateTime = value;
                RaisePropertyChanged("CurrentDateTime");
            }
        }

        /// <summary>
        /// 当前温湿度列表
        /// </summary>
        public ObservableCollection<THDataInfo> curTHDataList
        {
            get
            {
                return _curTHDataList;
            }
            set
            {
                _curTHDataList = value;
                RaisePropertyChanged("curTHDataList");
            }
        }

        /// <summary>
        ///
        /// </summary>
        public DelegateCommand ExitCommand
        {
            get
            {
                return _ExitCommand ?? (_ExitCommand = new DelegateCommand(OnExit));
            }
        }

        /// <summary>
        ///
        /// </summary>
        public DelegateCommand SelectStoreCommand => _SelectStoreCommand ?? (_SelectStoreCommand = new DelegateCommand(OnSelectStore));

        /// <summary>
        ///
        /// </summary>
        public StoreInfo SelStore
        {
            get
            {
                return _SelStore;
            }
            set
            {
                _SelStore = value;
                RaisePropertyChanged("SelStore");
            }
        }

        /// <summary>
        ///
        /// </summary>
        public DelegateCommand StartCommand
        {
            get
            {
                return _StartCommand ?? (_StartCommand = new DelegateCommand(OnStart));
            }
        }

        /// <summary>
        ///
        /// </summary>
        public ObservableCollection<StatisticsItem> StatisticsItems
        {
            get
            {
                return _StatisticsItems;
            }
            set
            {
                _StatisticsItems = value;
                RaisePropertyChanged("StatisticsItems");
            }
        }

        /// <summary>
        ///
        /// </summary>
        public DelegateCommand StopCommand
        {
            get
            {
                return _StopCommand ?? (_StopCommand = new DelegateCommand(OnStop));
            }
        }

        /// <summary>
        ///
        /// </summary>
        public ObservableCollection<StoreInfo> StoreInfos
        {
            get
            {
                return _StoreInfos;
            }
            set
            {
                _StoreInfos = value;
                RaisePropertyChanged("StoreInfos");
            }
        }

        public List<StoreRoomInfo> StoreRooms { get; set; }

        private void _readTime_Elapsed(object? sender, ElapsedEventArgs e)
        {
            if (SelStore != null)
            {
                LoadSlaveData();
            }
        }

        private void _timeTimer_Elapsed(object? sender, ElapsedEventArgs e)
        {
            CurrentDateTime = DateTime.Now.ToString("HH:mm:ss");
        }

        private async Task initCommunicationAsync()
        {
            await Task.Factory.StartNew(() =>
            {
                ModbusHelper.Instance.Open("COM1");
                _readTime.Start();
            });
        }

        private async Task InitDatasAsync()
        {
            List<Task> tasks = new List<Task>();
            tasks.Add(InitTimersAsync());
            tasks.Add(LoadStoreInfoAsync());
            tasks.Add(LoadStoreRoomsAsync());
            tasks.Add(LoadStoreRoomDatasAsync());
            tasks.Add(LoadSlaveLisAsync());
            tasks.Add(StatisticsDataAsync());
            tasks.Add(LoadAlarmLogAsync());
            tasks.Add(initCommunicationAsync());

            await Task.WhenAll(tasks.ToArray());
        }

        private async Task InitTimersAsync()
        {
            await Task.Factory.StartNew(() =>
            {
                _timeTimer = new System.Timers.Timer(1000);
                _timeTimer.AutoReset = true;
                _timeTimer.Elapsed += _timeTimer_Elapsed;
                _timeTimer.Start();

                _readTime = new System.Timers.Timer(1000);
                _readTime.AutoReset = true;
                _readTime.Elapsed += _readTime_Elapsed;
                _readTime.Start();
            });
        }

        private async Task LoadAlarmLogAsync()
        {
            await Task.Factory.StartNew(() =>
            {
                AlarmLogList = new ObservableCollection<AlarmLogInfo>();
            });
        }

        private async Task LoadSalveData(StoreInfo store)
        {
            await Task.Run(async () =>
            {
                try
                {
                    ushort[] datas = await ModbusHelper.Instance.ReadTHDataAsync(store.SlaveID, 0, (ushort)(store.Rooms.Count * 2));
                    if (datas != null && datas.Length > 0)
                    {
                        int roomNO = 1;
                        for (int i = 0; i < datas.Length; i += 2)
                        {
                            StoreRoomInfo room = store.Rooms.FirstOrDefault(z => z.RoomNO == roomNO);
                            Console.WriteLine($"{i} ROOMNO:{roomNO} 温度：{datas[i] / 10.0m} 湿度：{datas[i + 1] / 10.0m}");
                            ushort firstValue = datas[i];
                            ushort secondValue = datas[i + 1];
                            if (room != null)
                            {
                                room.LocalTH.Temperature = firstValue / 10.0m;
                                room.LocalTH.Humidity = secondValue / 1.0m;
                            }

                            roomNO++;
                        }
                    }
                    store.UpdateRoomState();
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            });
        }

        private async Task LoadSlaveData()
        {
            await Task.Run(async () =>
              {
                  foreach (var item in StoreInfos)
                  {
                      LoadSalveData(item);
                  }
                  UpdateStatisticsData();
              });
        }

        private async Task LoadSlaveLisAsync()
        {
            await Task.Factory.StartNew(() =>
            {
            });
        }

        private async Task LoadStoreInfoAsync()
        {
            await Task.Factory.StartNew(() =>
            {
                StoreInfos = new ObservableCollection<StoreInfo>();
                StoreInfos.Add(new StoreInfo { StoreNO = 1, StoreName = "库房1", SlaveID = 0x01 });
                StoreInfos.Add(new StoreInfo { StoreNO = 2, StoreName = "库房2", SlaveID = 0x02 });
            });
        }

        private void LoadStoreRoomDatas()
        {
            App.Current.Dispatcher.Invoke(() =>
            {
                curTHDataList.Clear();
                if (SelStore == null)
                    return;
                var rooms = StoreRooms.Where(z => z.StoreNO == SelStore.StoreNO).ToList();
                if (rooms.Count > 0)
                {
                    rooms.ForEach(p =>
                    {
                        curTHDataList.Add(p.LocalTH);
                    });
                }
            });
        }

        private async Task LoadStoreRoomDatasAsync()
        {
            await Task.Factory.StartNew(() =>
            {
                LoadStoreRoomDatas();
            });
        }

        private async Task LoadStoreRoomsAsync()
        {
            await Task.Factory.StartNew(() =>
            {
                StoreRooms = new List<StoreRoomInfo>();

                StoreInfo store1 = StoreInfos.FirstOrDefault(z => z.StoreNO == 1);
                if (null != store1)
                {
                    store1.Rooms.Add(new StoreRoomInfo { RoomNO = 1, RoomName = "库房1-101", StoreNO = 1, SlaveID = 0x01 });
                    store1.Rooms.Add(new StoreRoomInfo { RoomNO = 2, RoomName = "库房1-102", StoreNO = 1, SlaveID = 0x01 });
                    store1.Rooms.Add(new StoreRoomInfo { RoomNO = 3, RoomName = "库房1-103", StoreNO = 1, SlaveID = 0x01 });
                    store1.Rooms.Add(new StoreRoomInfo { RoomNO = 4, RoomName = "库房1-104", StoreNO = 1, SlaveID = 0x01 });
                    store1.Rooms.Add(new StoreRoomInfo { RoomNO = 5, RoomName = "库房1-105", StoreNO = 1, SlaveID = 0x01 });
                    store1.Rooms.Add(new StoreRoomInfo { RoomNO = 6, RoomName = "库房1-106", StoreNO = 1, SlaveID = 0x01 });
                    foreach (var item in store1.Rooms)
                    {
                        item.LocalTH = new THDataInfo { RoomNO = item.RoomNO, RoomName = item.RoomName, State = item.RoomState, Temperature = 0, Humidity = 0, SlaveID = item.SlaveID };
                    }
                    store1.UpdateRoomState();
                    StoreRooms.AddRange(store1.Rooms);
                }

                StoreInfo store2 = StoreInfos.FirstOrDefault(z => z.StoreNO == 2);
                if (null != store2)
                {
                    store2.Rooms.Add(new StoreRoomInfo { RoomNO = 1, RoomName = "库房2-201", StoreNO = 2, SlaveID = 0x02 });
                    store2.Rooms.Add(new StoreRoomInfo { RoomNO = 2, RoomName = "库房2-202", StoreNO = 2, SlaveID = 0x02 });
                    store2.Rooms.Add(new StoreRoomInfo { RoomNO = 3, RoomName = "库房2-203", StoreNO = 2, SlaveID = 0x02 });
                    store2.Rooms.Add(new StoreRoomInfo { RoomNO = 4, RoomName = "库房2-204", StoreNO = 2, SlaveID = 0x02 });
                    foreach (var item in store2.Rooms)
                    {
                        item.LocalTH = new THDataInfo { RoomNO = item.RoomNO, RoomName = item.RoomName, State = item.RoomState, Temperature = 0, Humidity = 0, SlaveID = item.SlaveID };
                    }
                    store2.UpdateRoomState();
                    StoreRooms.AddRange(store2.Rooms);
                }
            });
        }

        private void OnExit(object obj)
        {
            if (MessageBox.Show("确定退出系统吗？", "", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
            {
                _readTime.Stop();
                _timeTimer.Stop();
                ModbusHelper.Instance.Close();
                Environment.Exit(0);
            }
        }

        /// <summary>
        ///
        /// </summary>
        private void OnSelectStore(object obj)
        {
            LoadStoreRoomDatas();
        }

        /// <summary>
        ///
        /// </summary>
        private void OnStart(object obj)
        {
            _readTime.Start();
        }

        /// <summary>
        ///
        /// </summary>
        private void OnStop(object obj)
        {
            _readTime.Stop();
        }

        private async Task StatisticsDataAsync()
        {
            await Task.Factory.StartNew(() =>
            {
                StatisticsItems = new ObservableCollection<StatisticsItem>();
                StatisticsItems.Add(new StatisticsItem { ItemNote = "库房总数", ItemState = 0, ItemValue = 25 });
                StatisticsItems.Add(new StatisticsItem { ItemNote = "正常状态", ItemState = 1, ItemValue = 20 });
                StatisticsItems.Add(new StatisticsItem { ItemNote = "温度异常", ItemState = 2, ItemValue = 3 });
                StatisticsItems.Add(new StatisticsItem
                {
                    ItemNote = "湿度异常",
                    ItemState = 3,
                    ItemValue = 1
                });
                StatisticsItems.Add(new StatisticsItem
                {
                    ItemNote = "温湿度异常",
                    ItemState = 4,
                    ItemValue = 1
                });
            });
        }

        private void UpdateStatisticsData()
        {
            App.Current.Dispatcher.Invoke(() =>
            {
                StatisticsItem statisticsItem = StatisticsItems.SingleOrDefault(z => z.ItemState == 0);
                if (statisticsItem != null)
                    statisticsItem.ItemValue = StoreInfos.Where(z => z.Rooms.Count > 0).Select(z => z.Rooms.Count).Sum();
                statisticsItem = StatisticsItems.SingleOrDefault(z => z.ItemState == 1);
                if (statisticsItem != null)
                {
                    statisticsItem.ItemValue = StoreInfos.SelectMany(z => z.Rooms).Where(z => z.RoomState == 1).Count();
                }
                statisticsItem = StatisticsItems.SingleOrDefault(z => z.ItemState == 2);
                if (statisticsItem != null)
                {
                    statisticsItem.ItemValue = StoreInfos.SelectMany(z => z.Rooms).Where(z => z.RoomState == 2).Count();
                }
                statisticsItem = StatisticsItems.SingleOrDefault(z => z.ItemState == 3);
                if (statisticsItem != null)
                {
                    statisticsItem.ItemValue = StoreInfos.SelectMany(z => z.Rooms).Where(z => z.RoomState == 3).Count();
                }
                statisticsItem = StatisticsItems.SingleOrDefault(z => z.ItemState == 4);
                if (statisticsItem != null)
                {
                    statisticsItem.ItemValue = StoreInfos.SelectMany(z => z.Rooms).Where(z => z.RoomState == 4).Count();
                }
            });
        }
    }
}